package com.hhf.rpa.job.service;

import com.hhf.rpa.engine.model.ScriptExecConfigurer;
import com.hhf.rpa.engine.service.ScriptExecutor;
import com.hhf.rpa.glue.GlueTypeEnum;
import com.hhf.rpa.job.entity.BaseJob;
import com.hhf.rpa.job.entity.BaseJobLog;
import com.hhf.rpa.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.time.LocalDateTime;

@Slf4j
@Service
public class BaseJobHandler {
    @Autowired
    private BaseJobService baseJobService;
    @Autowired
    private BaseJobLogService baseJobLogService;
    @Autowired
    private ScriptExecutor scriptEngineDependencyInterfaceExecutor;
    @Autowired
    private ScriptExecutor simpleScriptExecutor;

    /**
     *
     * @param baseJob
     * @param execType 1自动执行， 2手动执行
     */
    public void execHandler(BaseJob baseJob, Integer execType) {
        Integer jobId = baseJob.getJobId();
        BaseJob job = baseJobService.getJobById(jobId);
        Assert.notNull(job, "任务不存在");
        if(job.getExecStatus() == 1) {
            log.debug("任务已经在执行中，可能已被其它节点执行");
            return;
        }
        boolean b = baseJobService.updateJobExecStatus(jobId, 0, 1);
        if(!b) {
            log.debug("任务已有节点执行，本节点不执行");
            return;
        }
        log.info("**********************任务开始在本节点执行********************");
        BaseJobLog jobLog = new BaseJobLog();
        BeanUtils.copyProperties(job,jobLog);
        jobLog.setExecType(execType);
        jobLog.setExecStatus(1);
        jobLog.setCreated(LocalDateTime.now());
        try {
            InetAddress localHost = InetAddress.getLocalHost();
            jobLog.setHost(localHost == null ? null : localHost.getHostAddress());
        } catch (UnknownHostException e) {
            log.error(e.getMessage(), e);
        }
        baseJobLogService.save(jobLog);
        try {
            Object resultObj = execMethod(job);
            log.info("Job Result:{}", resultObj == null ? "" : resultObj.toString());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            jobLog.setExecStatus(0);
            String errMsg = pringStackTraceToString(e);
            errMsg = errMsg.length() < 15000 ? errMsg : errMsg.substring(0, 15000) + "...";
            jobLog.setExecMsg(errMsg);
        } finally {
            jobLog.setUpdated(LocalDateTime.now());
            baseJobLogService.saveOrUpdate(jobLog);
            baseJobService.updateJobExecStatus(jobId, 1, 0);
        }
    }

    private Object execMethod(BaseJob job) throws Exception {
        Object result = null;
        //使用glue限制：脚本需要实现JobHandler接口exec方法，多个参数使用json字符串
        String glueType = job.getGlueType();
        if (StringUtils.isNotBlank(glueType) && !GlueTypeEnum.CLASS.name().equals(glueType)) {
            ScriptExecConfigurer config = new ScriptExecConfigurer();
            config.setGlueType(job.getGlueType());
            config.setGlueCode(job.getGlueCode());
            config.setBeanName(job.getBeanName());
            config.setParams(job.getParams());
            result = scriptEngineDependencyInterfaceExecutor.execScript(config);
        } else {
            // 多个参数使用json字符串
            ScriptExecConfigurer config = new ScriptExecConfigurer();
            config.setClassName(job.getClassName());
            config.setMethod(job.getMethod());
            config.setParams(job.getParams());
            result = simpleScriptExecutor.execScript(config);
        }
        return result;
    }

    private static String pringStackTraceToString(Throwable t) {
        StringWriter sw = new StringWriter();
        t.printStackTrace( new PrintWriter(sw, true));
        return sw.getBuffer().toString();
    }

}
